package cn.itsource.org.service.impl;

import cn.itsource.basic.AjaxResult;
import cn.itsource.basic.PageList;
import cn.itsource.basic.commonenum.ErrorCode;
import cn.itsource.basic.constants.Constant;
import cn.itsource.basic.exception.CustomException;
import cn.itsource.org.domain.Department;
import cn.itsource.org.mapper.DepartmentMapper;
import cn.itsource.org.query.DepartmentQuery;
import cn.itsource.org.service.IDepartmentService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class DepartmentServiceImpl implements IDepartmentService {

    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Override
    public Department queryOne(Long id) {
        return departmentMapper.loadOne(id);
    }

    @Override
    public List<Department> queryAll() {
        return departmentMapper.loadAll();
    }

    @Override
    @Transactional
    public void add(Department department) {
        departmentMapper.insert(department);
        this.update(department);
        //删除缓存
        redisTemplate.delete(Constant.DEPT_TREE_KEY);
    }

    @Override
    @Transactional
    @CacheEvict(cacheNames = Constant.DEPT_TREE_KEY ,key = "'tree'" )
    public void update(Department department) {
        String dirPath = "/";
        //如果父级对象等于null，自己属于顶级部门
        if(department.getParent() == null){
            dirPath = dirPath + department.getId();
        }else{
            //查询父部门
            Department parent = departmentMapper.loadOne(department.getParent().getId());
            dirPath = parent.getDirPath()+"/"+department.getId();
        }
        department.setDirPath(dirPath);
        departmentMapper.update(department);
    }

    @Override
    @Transactional
    @CacheEvict(cacheNames = Constant.DEPT_TREE_KEY ,key = "'tree'" )
    public void delete(Long id) {
        departmentMapper.delete(id);
    }

    @Override
    public PageList<Department> queryPage(DepartmentQuery departmentQuery) {
        //查询总条数
        Long count = departmentMapper.queryCount(departmentQuery);
        //查询分页数据
        List<Department> rows = departmentMapper.queryData(departmentQuery);
        //封装成pageList
        return new PageList<>(count,rows);
    }

    @Override
    @Transactional
    @CacheEvict(cacheNames = Constant.DEPT_TREE_KEY ,key = "'tree'" )
    public void patchDelete(List<Long> ids) {
        departmentMapper.patchDelete(ids);
    }


    /**
     * 无限级部门树如何查询
     * 1.嵌套查询
     *      每次要查全表数据库操作频繁，性能低
     * 2.嵌套结果
     *       只能查询两级
     * 3.全部查出来重新组装数据【掌握】
     *      也会慢，但是后面可以使用缓存来解决
     *      ctrl+alt+m
     * @return
     */
    @Override
    @Cacheable(cacheNames = Constant.DEPT_TREE_KEY ,key = "'tree'" ) //xxx::xxx
    public List<Department> queryTree() {
        return getDeptTreeFromDb();
    }


//    public List<Department> queryTree1() {
//        //直接从缓存中取数据
//        List<Department> result = (List<Department>)redisTemplate.opsForValue().get(Constant.DEPT_TREE_KEY);
//        //如果缓存中没取到数据
//        if(result == null){
//            //如果缓存中没有去数据库查
//            result = getDeptTreeFromDb();
//            //添加缓存
//            redisTemplate.opsForValue().set(Constant.DEPT_TREE_KEY,result);
//        }
//        return result;
//    }

    private List<Department> getDeptTreeFromDb() {
        //查询出所有的dept
        List<Department> allDepts = departmentMapper.loadAll();
        HashMap<Long, Department> hm = new HashMap<>();
        //结果集
        List<Department> resultDept = new ArrayList<>();
//        Map<Long, Department> map = allDepts.stream().collect(Collectors.toMap(Department::getId, dept -> dept));
        for (Department allDept : allDepts) {
            hm.put(allDept.getId(),allDept);
        }
        for (Department dept : allDepts) {
            //找出所有的爹
            if(dept.getParent_id() == null){
                resultDept.add(dept);
            }else{
                //找出所有的儿子塞到爹的children里 dept在这里就是子部门了
//                for (Department parent : allDepts) {
//                    if(parent.getId().equals(dept.getParent_id())){
//                        //把儿子塞到爹的children里去
//                        parent.getChildren().add(dept);
//                    }
//                }
                Department parent = hm.get(dept.getParent_id());
                //把儿子塞到爹的children里去
                parent.getChildren().add(dept);
            }
        }
        return resultDept;
    }
}
